package org.finesys.common.security.core.config;

import org.finesys.common.security.core.support.AuthAccessDeniedHandler;
import org.finesys.common.security.core.support.AuthAuthenticationEntrypoint;
import org.finesys.common.security.core.support.AuthBearerTokenResolver;
import org.finesys.common.security.core.support.AuthOpaqueTokenIntrospector;
import org.finesys.common.security.core.support.PermissionService;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector;
import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver;

import com.fasterxml.jackson.databind.ObjectMapper;


@AutoConfiguration
@EnableConfigurationProperties(value = AuthPermitAllUrlProperties.class)
public class AuthResourceServerAutoConfiguration {


    /**
     * 接口权限判断工具
     *
     * @return （#pms.xxx）
     */
    @Bean("pms")
    PermissionService permissionService() {
        return new PermissionService();
    }

    /**
     * 请求令牌的抽取逻辑
     *
     * @param authSecurityProperties 对外暴露的接口列表
     * @return BearerTokenExtractor
     */
    @Bean
    BearerTokenResolver bearerTokenResolver(AuthPermitAllUrlProperties authPermitAllUrlProperties) {
        return new AuthBearerTokenResolver(authPermitAllUrlProperties);
    }

    /**
     * 资源服务器toke内省处理器
     *
     * @param oAuth2AuthorizationService token 存储实现
     * @return OpaqueTokenIntrospector
     */
    @Bean
    OpaqueTokenIntrospector authOpaqueTokenIntrospector(OAuth2AuthorizationService oAuth2AuthorizationService) {
        return new AuthOpaqueTokenIntrospector(oAuth2AuthorizationService);
    }


    /**
     * 用于处理403类型异常
     */
    @Primary
    @Bean
    AuthAccessDeniedHandler authAccessDeniedHandler() {
        return new AuthAccessDeniedHandler();
    }

    /**
     * 用于处理401类型异常
     */
    @Primary
    @Bean
    AuthAuthenticationEntrypoint authAuthenticationEntrypoint(ObjectMapper objectMapper,
                                                              MessageSource securityMessageSource) {
        return new AuthAuthenticationEntrypoint(objectMapper,
                securityMessageSource);
    }

    /**
     * 注入密码编码器
     */
    @Bean
    @ConditionalOnMissingBean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

}
